import 'dart:io';

import 'package:fixnum/fixnum.dart';
import 'package:grpc/grpc.dart';
import 'package:member_center_sdk/core/sdk_enum.dart';
import 'package:member_center_sdk/grpc/client.pbgrpc.dart';
import 'package:member_center_sdk/grpc/common.pb.dart';
import 'package:member_center_sdk/grpc_impl/base_client.dart';
import 'package:member_center_sdk/grpc_impl/grpc_result.dart';
import 'package:member_center_sdk/grpc_impl/member_client_channel.dart';

typedef void AuthHandler(GrpcResult grpcResult, String token);

class MemberClient extends BaseClient {
  static MemberClientChannel _channel;
  static MemberApiClient _client;
  AuthHandler authHandler;
  String _token;

  MemberClient(String host, int port, String token, this.authHandler)
      : super(host, port, () {
          _channel = MemberClientChannel(host, port, token,
              options: const ChannelOptions(
                  credentials: const ChannelCredentials.insecure()));
          _client = MemberApiClient(_channel);
          return _channel;
        }) {
    _token = token;
  }

  Future<GrpcResult<R>> _checkAuth<R>(
      Future<GrpcResult<R>> resultFuture) async {
    var result = await resultFuture;
    this.authHandler(result, _token);
    return result;
  }

  Future<GrpcResult<GetMemberResponse>> getMember() async {
    return await _checkAuth(doAction((options) {
      return _client.getMember(Empty(), options: options);
    }));
  }

  Future<GrpcResult<SetAvaterResponse>> setAvater(List<int> data) async {
    return await _checkAuth(doAction((options) {
      var newOptions = options.mergedWith(CallOptions(
        timeout: Duration(seconds: 30),
      ));
      return _client.setAvater(SetAvaterRequest()..avaterData = data,
          options: newOptions);
    }));
  }

  Future<GrpcResult<BoolValue>> setExt(String json) async {
    return await _checkAuth(doAction((options) {
      return _client.setExt(SetExtRequest()..jsonData = json, options: options);
    }));
  }

  Future<GrpcResult<BoolValue>> checkPassword(int pwdType) async {
    return await _checkAuth(doAction((options) {
      return _client.checkPassword(CheckPasswordRequest()..type = pwdType,
          options: options);
    }));
  }

  Future<GrpcResult<BoolValue>> setPassword(int pwdType, String oldPwd,
      String smsId, String code, String newPassword) async {
    return await _checkAuth(doAction((options) {
      return _client.setPassword(
          SetPasswordRequest()
            ..type = pwdType
            ..oldPassword = oldPwd
            ..smsId = smsId
            ..code = code
            ..password = newPassword,
          options: options);
    }));
  }

  Future<GrpcResult<BoolValue>> setChild(int memberId) async {
    return await _checkAuth(doAction((options) {
      return _client.setChild(MemberIdRequest()..memberId = Int64(memberId),
          options: options);
    }));
  }

  Future<GrpcResult<BoolValue>> bindPhone(String smsId, String code) async {
    DeviceType deviceType =
        Platform.isIOS ? DeviceType.Ios : DeviceType.Android;
    return await _checkAuth(doAction((options) {
      return _client.bindPhone(
          BindPhoneRequest()
            ..code = code
            ..deviceType = deviceType.index
            ..smsId = smsId,
          options: options);
    }));
  }
}
